package service

import (
	"fmt"
	"strings"
	"sync"

	"gitee.com/openeuler/PilotGo/sdk/logger"
	jobstatus "openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/common/enum/job"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/common/exec"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/job_history/dao"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/job_history/model"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/pkg/utils"
)

// 重试作业处理
func RetryJob(retryReq *model.TaskRetryRequest) (string, error) {
	logger.Debug("开始重试作业: jobId=%s, stepNum=%d, reuseEnv=%v, retryHosts=%s", retryReq.JobId, retryReq.StepNum, retryReq.ReuseEnv, retryReq.RetryHosts)
	// 1. 创建新的作业记录（包含基本信息、参数和子作业）
	newJobId := utils.GenerateUUID()
	newJobDTO, err := dao.CreateRetryJob(retryReq.JobId, newJobId, retryReq)
	if err != nil {
		return "", fmt.Errorf("创建重试作业记录失败: %v", err)
	}

	// 2. 初始化子作业结果记录
	if err = initSubJobResultsForRetry(newJobDTO, retryReq); err != nil {
		return "", fmt.Errorf("初始化子作业结果失败: %v", err)
	}

	// 3. 通知agent端执行重试
	err = triggerAgentRetry(newJobDTO, retryReq, newJobId)
	if err != nil {
		return "", fmt.Errorf("触发agent端重试失败: %v", err)
	}

	logger.Debug("作业重试准备完成: 原jobId=%s, 新jobId=%s, 重试次数=%d",
		retryReq.JobId, newJobId, newJobDTO.Job.RetryCount)
	return newJobId, nil
}

// 初始化子作业结果记录，支持部分主机和部分步骤的重试
func initSubJobResultsForRetry(jobDTO *model.JobDTO, retryReq *model.TaskRetryRequest) error {
	var hosts []string
	if retryReq.RetryHosts != "" {
		hosts = strings.Split(retryReq.RetryHosts, ",")
	} else {
		hosts = strings.Split(jobDTO.Job.ExecHosts, ",")
	}

	var allSubJobResults []*model.SubJobStepResult

	for _, ip := range hosts {
		for _, subJob := range jobDTO.SubJobs {
			// 如果指定了起始步骤，则只需要初始化从该步骤开始的子作业
			if retryReq.StepNum > 0 && subJob.StepNum < retryReq.StepNum {
				continue
			}

			status := jobstatus.SubJobNotRun
			subJobResult := &model.SubJobStepResult{
				JobId:        jobDTO.Job.JobId,
				WorkflowId:   jobDTO.Job.WorkflowId,
				IP:           ip,
				StepNum:      subJob.StepNum,
				SubJobStatus: status,
			}
			allSubJobResults = append(allSubJobResults, subJobResult)
		}
	}

	return dao.SaveSubJobStepResult(allSubJobResults)
}

// 触发agent端执行重试
func triggerAgentRetry(jobDTO *model.JobDTO, retryReq *model.TaskRetryRequest, newJobId string) error {
	// 构建重试请求，包含原jobId和新jobId
	retryTaskReq := &model.TaskRetryRequest{
		JobId:      retryReq.JobId,
		StepNum:    retryReq.StepNum,
		ReuseEnv:   retryReq.ReuseEnv,
		RetryHosts: retryReq.RetryHosts,
	}

	// 确定要发送的主机列表
	var hosts []string
	if retryReq.RetryHosts != "" {
		hosts = strings.Split(retryReq.RetryHosts, ",")
	} else {
		hosts = strings.Split(jobDTO.Job.ExecHosts, ",")
	}

	var wg sync.WaitGroup
	errors := make([]error, len(hosts))

	for i, ip := range hosts {
		wg.Add(1)
		go func(index int, hostIP string) {
			defer wg.Done()
			errors[index] = exec.RetryJob(hostIP, retryTaskReq, newJobId)
			if errors[index] != nil {
				logger.Error("通知主机%s执行重试失败: %v", hostIP, errors[index])
			}
		}(i, ip)
	}

	wg.Wait()

	// 检查是否有错误发生, 但不中断整体流程, 部分主机失败不应影响其他主机的重试
	hasError := false
	for _, err := range errors {
		if err != nil {
			hasError = true
			logger.Error("部分主机重试失败: %v", err)
		}
	}

	if hasError {
		logger.Warn("部分主机重试请求发送失败，但不会中断整个重试流程")
	}

	return nil
}

// 添加获取关联任务的服务方法
func GetRelatedJobs(jobId string) ([]*model.Job, error) {
	return dao.GetRelatedJobs(jobId)
}

// 获取完整重试链的服务方法
func GetRetryChain(jobId string) ([]*model.Job, error) {
	job, err := dao.GetJobResult(jobId)
	if err != nil {
		return nil, err
	}

	rootJobId := job.JobId
	if job.RootJobId != "" {
		rootJobId = job.RootJobId
	}

	return dao.GetRetryChain(rootJobId)
}
